package com.ithuameng.admin.app.system.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ithuameng.admin.app.system.model.Role;
import com.ithuameng.admin.app.system.model.User;
import com.ithuameng.admin.app.system.model.admin.qo.UserQo;
import com.ithuameng.admin.app.system.model.admin.vo.*;
import com.ithuameng.admin.app.system.model.vo.AdminPageResVo;
import com.ithuameng.admin.app.system.model.vo.R;
import com.ithuameng.admin.app.system.service.IRoleService;
import com.ithuameng.admin.app.system.service.IUserRoleService;
import com.ithuameng.admin.app.system.service.IUserService;
import com.ithuameng.admin.enums.CommonError;
import com.ithuameng.admin.utils.SecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户控制器
 *
 * @author ithuameng
 */
@Api(tags = "用户控制器")
@RestController
@RequestMapping(value = "/admin/v1/user")
public class UserController extends AdminBaseController {

    @Resource
    private IUserService userService;

    @Resource
    private IRoleService roleService;

    @Resource
    private IUserRoleService userRoleService;

    @ApiOperation("获取用户列表")
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/list")
    public R<AdminPageResVo<User>> list(UserQo userQo) {
        if (StringUtils.isNotBlank(userQo.getUsername())) {
            userQo.setUsername(userQo.getUsername().toLowerCase());
        }
        Page<User> page = new Page<>(userQo.getPageNumber(), userQo.getPageSize());
        IPage<User> pageList = userService.listUser(page, userQo);
        AdminPageResVo<User> userPage = new AdminPageResVo<>();
        userPage.setRecords(pageList.getRecords());
        userPage.setPage(pageList.getPages());
        userPage.setTotal(pageList.getTotal());
        return new R<>(userPage);
    }

    @ApiOperation("根据用户编号获取详细信息")
    @GetMapping("/{userId}")
    public R<UserVo> getInfo(@PathVariable(value = "userId") Long userId) {
        User user = userService.getById(userId);
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user, userVo);
        List<Role> allRoles = roleService.list();
        List<Role> roles = User.ADMIN_ID.equals(userId) ? allRoles
                : allRoles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList());
        userVo.setRoles(roles);
        List<Long> roleIds = userRoleService.listRoleByUserId(userId);
        userVo.setRoleIds(roleIds);
        return new R<>(userVo);
    }

    @ApiOperation("新增用户")
    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @PostMapping("/add")
    public R<Boolean> add(@Validated @RequestBody UserAddVo userAddVo) {
        if (!userService.checkUsernameUnique(userAddVo.getUsername())) {
            return new R<>(CommonError.BIZ_ERR, "登录名称已存在");
        }
        if (!userService.checkMobileUnique(userAddVo.getMobile())) {
            return new R<>(CommonError.BIZ_ERR, "手机号码已存在");
        }
        if (userAddVo.getStatus() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择状态");
        }
        User user = new User();
        BeanUtils.copyProperties(userAddVo, user);
        user.setUsername(user.getUsername().toLowerCase());
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userService.saveWithRoles(user, userAddVo.getRoleIds());
        return new R<>(CommonError.OK, "添加成功");
    }

    @ApiOperation("修改用户")
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @PostMapping("/edit")
    public R<Boolean> edit(@Validated @RequestBody UserEditVo userEditVo) {
        if (!userService.checkMobileUnique(userEditVo.getMobile(), userEditVo.getId())) {
            return new R<>(CommonError.BAD_REQUEST, "手机号码已存在");
        }
        if (userEditVo.getStatus() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择状态");
        }
        User userDO = new User();
        BeanUtils.copyProperties(userEditVo, userDO);
        // 禁止修改密码
        userDO.setPassword(null);
        userService.updateWithRoles(userDO, userEditVo.getRoleIds());
        return new R<>(CommonError.OK, "更新成功");
    }

    @ApiOperation("删除用户")
    @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @PostMapping("delete/{userIds}")
    public R<Boolean> remove(@PathVariable Long[] userIds) {
        if (userIds == null) {
            return new R<>(CommonError.BAD_REQUEST, "未选择用户");
        }
        Long uid = SecurityUtils.getUserId();
        if (uid == null) {
            return new R<>(CommonError.BAD_REQUEST, "未获取到当前用户");
        }
        if (ArrayUtils.contains(userIds, uid)) {
            return new R<>(CommonError.BAD_REQUEST, "当前用户不能删除");
        }
        if (ArrayUtils.contains(userIds, User.ADMIN_ID)) {
            return new R<>(CommonError.BAD_REQUEST, "超级管理员不能删除");
        }
        userService.deleteUserByIds(userIds);
        return new R<>(CommonError.OK, "删除成功");
    }

    @ApiOperation("重置密码")
    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @PostMapping("/resetPwd")
    public R<Boolean> resetPwd(@Validated @RequestBody UserResetPwdVo userResetPwdVo) {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encrptPwd = passwordEncoder.encode(userResetPwdVo.getPassword());
        userService.resetPassword(userResetPwdVo.getUserId(), encrptPwd);
        return new R<>(CommonError.OK, "密码重置成功");
    }

    @ApiOperation("状态修改")
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @PostMapping("/changeStatus")
    public R<Boolean> changeStatus(@Validated @RequestBody UserStatusUpdateVo userStatusUpdateVo) {
        if (User.ADMIN_ID.equals(userStatusUpdateVo.getUserId())) {
            return new R<>(CommonError.BAD_REQUEST, "超级管理员状态不能修改");
        }
        if (userStatusUpdateVo.getStatus() == null) {
            return new R<>(CommonError.BIZ_ERR, "请选择状态");
        }
        userService.updateStatus(userStatusUpdateVo.getUserId(), userStatusUpdateVo.getStatus());
        return new R<>(CommonError.OK, "更新成功");
    }

    @ApiOperation("根据用户编号获取授权角色")
    @GetMapping("/authRole/{userId}")
    public R<UserAuthDetailVo> authRole(@PathVariable("userId") Long userId) {
        User user = userService.getById(userId);
        List<UserRoleAuthVo> roles = roleService.selectRolesByUserId(userId);
        UserAuthDetailVo userAuthDetailVO = new UserAuthDetailVo();
        UserAuthUserInfo userInfo = new UserAuthUserInfo(user.getId(), user.getNickname(), user.getUsername());
        userAuthDetailVO.setUser(userInfo);
        if (User.ADMIN_ID.equals(SecurityUtils.getLoginUser().getId())) {
            userAuthDetailVO.setRoles(roles);
        } else {
            userAuthDetailVO.setRoles(roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        }
        return new R<>(userAuthDetailVO);
    }

    @ApiOperation("用户授权角色")
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @PostMapping("/authRole")
    public R<Boolean> insertAuthRole(Long userId, Long[] roleIds) {
        userService.updateUserRole(userId, roleIds);
        return new R<>(CommonError.OK, "用户授权角色成功");
    }

    @ApiOperation("修改用户密码")
    @PostMapping("/index/resetPwd")
    public R<Boolean> indexResetPwd(@Validated @RequestBody UserIndexResetPwdVo userIndexResetPwdVo) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        // 旧密码是否正确
        User user = userService.getUserByUsername(userIndexResetPwdVo.getUsername());
        if (!bCryptPasswordEncoder.matches(userIndexResetPwdVo.getOldPassword(), user.getPassword())) {
            return new R<>(CommonError.BAD_REQUEST, "旧密码输入有误");
        }
        // 新密码与确认密码是否一致
        if (!userIndexResetPwdVo.getNewPassword().equals(userIndexResetPwdVo.getConfirmPassword())) {
            return new R<>(CommonError.BAD_REQUEST, "新密码与确认密码不一致");
        }
        // 根据新密码
        user.setPassword(bCryptPasswordEncoder.encode(userIndexResetPwdVo.getNewPassword()));
        userService.updateById(user);

        return new R<>(CommonError.OK, "修改成功");
    }
}
